package com.demarc.pesquisas.negocio.service.entrevista;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.primefaces.model.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demarc.pesquisas.infraestrutura.excecao.NegocioException;
import com.demarc.pesquisas.infraestrutura.excecao.NegocioExceptionUtil;
import com.demarc.pesquisas.infraestrutura.mensagem.Mensagem;
import com.demarc.pesquisas.infraestrutura.persistencia.ResultadoPaginado;
import com.demarc.pesquisas.infraestrutura.util.utils.DemarPesquisasUtil;
import com.demarc.pesquisas.negocio.dao.AbstractDAO;
import com.demarc.pesquisas.negocio.dao.EntrevistaDAO;
import com.demarc.pesquisas.negocio.dto.DetalheEntrevistaDTO;
import com.demarc.pesquisas.negocio.dto.EntrevistaDTO;
import com.demarc.pesquisas.negocio.dto.RelatorioAgrupamentoLocalidadeDTO;
import com.demarc.pesquisas.negocio.dto.RelatorioFiltroDTO;
import com.demarc.pesquisas.negocio.entidade.domicilio.Morador;
import com.demarc.pesquisas.negocio.entidade.entrevista.Entrevista;
import com.demarc.pesquisas.negocio.entidade.entrevista.EntrevistaFiltro;
import com.demarc.pesquisas.negocio.entidade.pesquisa.Pesquisa;
import com.demarc.pesquisas.negocio.service.AbstractService;
import com.demarc.pesquisas.negocio.service.domicilio.IDomicilioService;
import com.demarc.pesquisas.negocio.util.ConstantesMensagens;
import com.demarc.pesquisas.negocio.util.ValidacaoUtils;

@Service
public class EntrevistaService extends AbstractService<Entrevista, Long> implements
        IEntrevistaService {

    private static final Logger LOGGER = Logger.getLogger(EntrevistaService.class);

    @Autowired
    private EntrevistaDAO dao;

    @Autowired
    private IDomicilioService domicilioService;

    @Override
    public AbstractDAO<Entrevista, Long> getDAO() {
        return dao;
    }

    public EntrevistaDAO getDao() {
        return dao;
    }

    public void setDao(EntrevistaDAO dao) {
        this.dao = dao;
    }

    @Override
    public List<RelatorioAgrupamentoLocalidadeDTO> consultarRelatorioTotalizador(
            RelatorioFiltroDTO filtro) {
        return dao.consultarRelatorioTotalizador(filtro);
    }

    @Override
    public List<DetalheEntrevistaDTO> consultarRelatorioDetalhes(RelatorioFiltroDTO filtro) {
        List<Entrevista> entrevistas = dao.consultarRelatorioDetalhes(filtro);
        List<DetalheEntrevistaDTO> detalhesEntrevistaDTO = new ArrayList<DetalheEntrevistaDTO>();
        for (Entrevista entrevista : entrevistas) {
            detalhesEntrevistaDTO.add(DetalheEntrevistaDTO.converter(entrevista));
        }
        return detalhesEntrevistaDTO;
    }

    @Override
    public ResultadoPaginado<EntrevistaDTO> consultar(EntrevistaFiltro entrevistaFiltro, int first,
            int pageSize, String sortField, SortOrder sortOrder) {

        DemarPesquisasUtil.adicionarOrdenacaoFiltro(entrevistaFiltro.getFiltro(), first, pageSize,
                sortField, sortOrder);
        return this.dao.consultar(entrevistaFiltro);
    }

    @Override
    public List<String> listarLocalidades(Pesquisa pesquisa) {
        if (pesquisa == null) {
            throw new IllegalArgumentException("Pesquisa é obrigatório para a consulta");
        }
        return this.dao.listarLocalidades(pesquisa);
    }

    @Override
    public void salvar(Entrevista entrevista) {
        LOGGER.info(":::::::::::::::: Enviando entrevista com SEQUENCIAL"
                + entrevista.getSequencial() + " para ser Salva");

        super.salvar(entrevista);

        LOGGER.info(":::::::::::::::: Entrevista com SEQUENCIAL " + entrevista.getSequencial()
                + " SALVA com sucesso");

        LOGGER.info(":::::::::::::::: Enviando domicílio " + entrevista.getDomicilio().getId()
                + " para ser atualizado ");

        domicilioService.alterar(entrevista.getDomicilio());

        LOGGER.info(":::::::::::::::: Domicílio " + entrevista.getDomicilio().getId()
                + " atualizado com sucesso");
    }

    @Override
    public void alterar(Entrevista entrevista) {
        LOGGER.info(":::::::::::::::: Enviando entrevista com SEQUENCIAL"
                + entrevista.getSequencial() + " para ser ALTERADA");

        super.alterar(entrevista);

        LOGGER.info(":::::::::::::::: Entrevista com SEQUENCIAL" + entrevista.getSequencial()
                + " ALTERADA com sucesso");

        LOGGER.info(":::::::::::::::: Enviando domicílio " + entrevista.getDomicilio().getId()
                + " para ser atualizado ");

        domicilioService.alterar(entrevista.getDomicilio());

        LOGGER.info(":::::::::::::::: Domicílio " + entrevista.getDomicilio().getId()
                + " atualizado com sucesso");
    }

    @Override
    public void excluir(Entrevista entrevista) {
        LOGGER.info(":::::::::::::::: Enviando entrevista com SEQUENCIAL"
                + entrevista.getSequencial() + " para ser EXCLUÍDA");

        super.excluir(entrevista);

        LOGGER.info(":::::::::::::::: Entrevista com SEQUENCIAL" + entrevista.getSequencial()
                + " EXCLUÍDA com sucesso");
    }

    @Override
    public void validarInclusao(Entrevista entrevista) {
        validar(entrevista);
    }

    @Override
    public void validarAlteracao(Entrevista entrevista) {
        validar(entrevista);
    }

    private void validar(Entrevista entrevista) {
        validarCamposObrigatorios(entrevista);
        validarExistenciaCPFCadastrado(entrevista);
        validarCPFMoradores(entrevista);
        validarSequencialIgual(entrevista);
    }

    private void validarCamposObrigatorios(Entrevista entrevista) {
        List<Mensagem> erros = new ArrayList<Mensagem>();
        erros.addAll(entrevista.validar());
        erros.addAll(entrevista.getEntrevistado().validar());
        erros.addAll(entrevista.getDomicilio().validar());
        for (Morador morador : entrevista.getDomicilio().getMoradores()) {
            erros.addAll(morador.validar());
        }
        NegocioExceptionUtil.lancarExcecao(erros);
    }

    private void validarExistenciaCPFCadastrado(Entrevista entrevista) {
        if (entrevista != null && entrevista.getEntrevistado() != null
                && StringUtils.isNotBlank(entrevista.getEntrevistado().getCpf())) {

            if (dao.entrevistadoJaCadastradoComCPF(entrevista)) {
                throw new NegocioException(ConstantesMensagens.ERRO_0003, entrevista
                        .getEntrevistado().getCpf());
            }
        }
    }

    private void validarCPFMoradores(Entrevista entrevista) {
        validarMoradorComCpfValido(entrevista);
    }

    private void validarMoradorComCpfValido(Entrevista entrevista) {
        for (Morador morador : entrevista.getDomicilio().getMoradores()) {
            if (StringUtils.isNotBlank(morador.getCpf())) {
                ValidacaoUtils.validarCPF(morador.getCpf(), morador.getNome());
            }
        }
    }

    public void validarSequencialIgual(Entrevista entrevista) {
        if (dao.existeSequencialIgual(entrevista)) {
            throw new NegocioException(ConstantesMensagens.ERRO_0001);
        }
    }

    public IDomicilioService getDomicilioService() {
        return domicilioService;
    }

    public void setDomicilioService(IDomicilioService domicilioService) {
        this.domicilioService = domicilioService;
    }
}
